package org.jeecg.modules.iot.util;


import org.jeecg.modules.iot.model.LocationJson;

import java.util.ArrayList;
import java.util.List;

public class DouglasPeucker {

    public static List<LocationJson> simplify(List<LocationJson> points, double epsilon) {
        if (points == null || points.size() < 3) {
            return points;
        }

        boolean[] keep = new boolean[points.size()];
        keep[0] = true;
        keep[points.size() - 1] = true;

        simplify(points, 0, points.size() - 1, epsilon, keep);

        List<LocationJson> result = new ArrayList<>();
        for (int i = 0; i < keep.length; i++) {
            if (keep[i]) {
                result.add(points.get(i));
            }
        }

        return result;
    }

    private static void simplify(List<LocationJson> points, int start, int end, double epsilon, boolean[] keep) {
        double maxDistance = 0.0;
        int index = 0;

        for (int i = start + 1; i < end; i++) {
            double distance = perpendicularDistance(points.get(start), points.get(end), points.get(i));
            if (distance > maxDistance) {
                maxDistance = distance;
                index = i;
            }
        }

        if (maxDistance > epsilon) {
            keep[index] = true;
            simplify(points, start, index, epsilon, keep);
            simplify(points, index, end, epsilon, keep);
        }
    }

    private static double perpendicularDistance(LocationJson start, LocationJson end, LocationJson point) {
        double area = Math.abs(start.getLat() * end.getLng() + end.getLat() * point.getLng() + point.getLat() * start.getLng()
                - end.getLat() * start.getLng() - point.getLat() * end.getLng() - start.getLat() * point.getLng());
        double bottom = Math.sqrt(Math.pow(start.getLat() - end.getLat(), 2) + Math.pow(start.getLng() - end.getLng(), 2));
        return area / bottom * 2.0;
    }
}